import axios from 'axios'
import { localCache } from '../storage'
import { message } from 'antd'
import type {
	AxiosInstance,
	AxiosResponse,
	AxiosRequestConfig,
	InternalAxiosRequestConfig
} from 'axios'

// 请求配置类型
interface IRequestConfig<T = AxiosResponse> extends AxiosRequestConfig {
	interceptors?: {
		requestSuccessFn?: (config: AxiosRequestConfig) => InternalAxiosRequestConfig
		requestFailureFn?: (err: any) => any
		responseSuccessFn?: (res: T) => T
		responseFailureFn?: (err: any) => any
	}
}

class Request {
	private instance: AxiosInstance

	constructor(config: IRequestConfig) {
		this.instance = axios.create(config)

		this.instance.interceptors.request.use(
			(config) => {
				const token = localCache.getItem('token')
				if (token && config.headers) {
					config.headers['Authorization'] = token
				}
				return config
			},
			(err) => new Error(err)
		)
		this.instance.interceptors.response.use(
			(res) => {
				// 全局响应成功 - 返回真正的接口数据(data)
				if (res.data.code === 200) {
					return res.data
				} else {
					return Promise.reject(res.data)
				}
			},
			(err) => {
				message.error(err)
				return new Error(err)
			}
		)

		this.instance.interceptors.request.use(
			config.interceptors?.requestSuccessFn,
			config.interceptors?.requestFailureFn
		)
		this.instance.interceptors.response.use(
			config.interceptors?.responseSuccessFn,
			config.interceptors?.responseFailureFn
		)
	}

	private request<V = any>(config: IRequestConfig<V>) {
		if (config.interceptors?.requestSuccessFn) {
			config = config.interceptors.requestSuccessFn(config)
		}
		return new Promise<V>((resolve, reject) => {
			this.instance
				.request<any, V>(config)
				.then((res) => {
					if (config.interceptors?.responseSuccessFn)
						res = config.interceptors.responseSuccessFn(res)
					resolve(res)
				})
				.catch((err) => {
					if (config.interceptors?.responseFailureFn)
						err = config.interceptors.responseFailureFn(err)
					reject(err)
				})
		})
	}

	get<Res = any>(config: IRequestConfig<Res>) {
		return this.request<Res>({ ...config, method: 'GET' })
	}
	post<Res = any>(config: IRequestConfig<Res>) {
		return this.request<Res>({ ...config, method: 'POST' })
	}
	put<Res = any>(config: IRequestConfig<Res>) {
		return this.request<Res>({ ...config, method: 'PUT' })
	}
	patch<Res = any>(config: IRequestConfig<Res>) {
		return this.request<Res>({ ...config, method: 'PATCH' })
	}
	delete<Res = any>(config: IRequestConfig<Res>) {
		return this.request<Res>({ ...config, method: 'DELETE' })
	}
}

export default Request
